package io.vertx.greatbit;

import java.io.File;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.vertx.java.core.Handler;
import org.vertx.java.core.http.HttpServerRequest;
import org.vertx.java.core.http.HttpServerResponse;
import org.vertx.java.platform.Verticle;

import com.fasterxml.jackson.databind.ObjectMapper;

public class AnyWhere extends Verticle {
    public static final Logger logger = LoggerFactory.getLogger(AnyWhere.class);
    private static String USER_DIR;
    private static int HTTP_PORT;

    private static Settings settings;
    private static ExecutorService executor;

    static {
        try {
            USER_DIR = System.getProperty("user.dir");
            HTTP_PORT = (System.getProperty("http.port") != null) ? Integer.valueOf(System.getProperty("http.port")) : 80;

            ObjectMapper mapper = new ObjectMapper();
            URL url = AnyWhere.class.getClassLoader().getResource("./settings.json");
            settings = mapper.readValue(url, Settings.class);
            executor = Executors.newFixedThreadPool(settings.getPool());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void start() {
        vertx.createHttpServer().requestHandler(new Handler<HttpServerRequest>() {
            public void handle(HttpServerRequest req) {
                HttpServerResponse resp = req.response();
                try {
                    String fileName = req.path().equals("/") ? "index.html" : req.path().substring(1);
                    File file = new File(USER_DIR, fileName);
                    //accept cross-domain
                    resp.putHeader("P3P", "CP=\"NON DSP COR CURa ADMa DEVa TAIa PSAa PSDa IVAa IVDa CONa HISa TELa OTPa OUR UNRa IND UNI COM NAV INT DEM CNT PRE LOC\"");
                    resp.putHeader("Access-Control-Allow-Origin", "*");
                    if (logger.isInfoEnabled()) {
                        logger.info("#header:{}", resp.headers());
                        for (Map.Entry<String, String> entry : resp.headers().entries()) {
                            logger.info("#key:{} value:{}", entry.getKey(), entry.getValue());
                        }
                    }
                    if (isVaild(file)) {
                        resp.sendFile(file.getAbsolutePath());
                    } else {
                        resp.setStatusCode(HttpURLConnection.HTTP_NOT_FOUND);
                        if (logger.isInfoEnabled()) {
                            executor.execute(new Runnable() {
                                @Override
                                public void run() {
                                    logger.debug("#{}# {}.", settings.getExcludes(), settings.getPool());
                                }
                            });
                        }
                    }
                } catch (Exception e) {
                    resp.setStatusCode(HttpURLConnection.HTTP_BAD_REQUEST);
                }
            }
        }).listen(HTTP_PORT);
        logger.info("#WEB_HOME#:{} listen to port {}.", USER_DIR, HTTP_PORT);
    }

    private boolean isVaild(File file) {
        if (file == null || !file.canRead()) return false;
        else {
            boolean isExclude = true;
            for (String prefix : settings.getExcludes()) {
                if (file.getName().startsWith(prefix)) {
                    isExclude = false;
                    break;
                } else {
                    continue;
                }
            }
            return isExclude && Files.exists(file.toPath());
        }
    }
}
